package com.ydcode.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

/**
 * 对文件操作辅助类
 * 
 * @author YUPENG.LI
 * @version 1.0.0.0
 * 
 */
@SuppressWarnings("unused")
public class FileUtil {

	/**
	 * 获取项目地址
	 */
	private static String itemsUrl;

	/**
	 * 后缀组
	 */
	public List<String> exts = new ArrayList<String>();

	/**
	 * 包含文件名称
	 */
	public List<String> containNames = new ArrayList<String>();

	/**
	 * 过虑包含的文件名称
	 */
	public List<String> neglectNames = new ArrayList<String>();

	/**
	 * 文件集合
	 */
	private List<File> files = new ArrayList<File>();

	/**
	 * 文件路径集合
	 */
	private List<String> filePaths = new ArrayList<String>();

	/**
	 * 文件名称集合
	 */
	private List<String> fileNameAndExts = new ArrayList<String>();

	/**
	 * 文件名称集合
	 */
	private List<String> fileNames = new ArrayList<String>();

	/**
	 * 文件后缀集合
	 */
	private List<String> filePrefixs = new ArrayList<String>();

	/**
	 * 保存编码
	 */
	public String saveSncode = "UTF-8";

	/**
	 * 是否创建Action
	 */
	public boolean isAction = false;

	/**
	 * 原本文件编码
	 */
	public String formerSncode;

	/**
	 * 读取文件
	 * 
	 * @param file
	 * @return
	 */
	public String loadFile(File file) {
		String context = null;
		try {
			java.io.BufferedInputStream br = new BufferedInputStream(
					new java.io.FileInputStream(file));
			byte[] bts = new byte[br.available()];
			br.read(bts);
			br.close();
			context = new String(bts);
			formerSncode = getEncoding(context);
			if (!formerSncode.equals(saveSncode)) {
				context = new String(bts, saveSncode);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return context;
	}

	/**
	 * 读取文件
	 * 
	 * @param path
	 * @return
	 */
	public String loadFile(String path) {
		return loadFile(new File(path));
	}

	/**
	 * 保存文件
	 * 
	 * @param context
	 *            文件内容
	 * @param filePath
	 *            文件路径
	 * @return
	 */
	public File saveFile(String context, String filePath) {
		return saveFile(context, new File(filePath.trim()));
	}

	/**
	 * 保存文件
	 * 
	 * @param context
	 *            文件内容
	 * @param filePath
	 *            文件路径
	 * @param isBestrow
	 *            是否覆盖
	 * @return
	 */
	public File saveFile(String context, String filePath, Boolean isBestrow) {
		return saveFile(context, new File(filePath.trim()), isBestrow);
	}

	/**
	 * 保存文件
	 * 
	 * @param context
	 *            文件内容
	 * @param file
	 *            文件
	 * @param isBestrow
	 *            是否覆盖
	 * @return
	 */
	public File saveFile(String context, File file, Boolean isBestrow) {
		if (!isBestrow && file.exists()) {
			System.out.println("文件已存在: " + file.getPath() + "\t\t[ 跳过 ]");
			return file;
		}
		return saveFile(context, file);
	}

	/**
	 * 保存文件
	 * 
	 * @param context
	 * @param file
	 * @return
	 */
	public File saveFile(String context, File file) {
		try {
			if (!file.getParentFile().exists()) {
				file.getParentFile().mkdirs();
				System.out.println("创建文件夹: " + file.getParentFile().getName());
			}
			
			if (file.exists()) {
				System.out.println("文件已存在: " + file.getPath() + "\t\t[ 覆盖 ]");
				return file;
			}
			
			BufferedOutputStream bw = new BufferedOutputStream(
					new FileOutputStream(file));
			bw.write(context.getBytes(saveSncode));
			bw.close();
			System.out.println(file.getName() + "\t保存成功!");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return file;
	}

	/**
	 * 备份文件
	 * 
	 * @param file
	 * @return
	 */
	public File SaveBak(String filePath) {
		File file = new File(filePath);
		File fileBak = new File(filePath + ".bak");
		file.compareTo(fileBak);
		return fileBak;
	}

	/**
	 * 备份文件
	 * 
	 * @param file
	 * @param fileBak
	 * @return
	 */
	public File SaveBak(String filePath, String fileBakPath) {
		File file = new File(filePath);
		File fileBak = new File(fileBakPath);
		file.compareTo(fileBak);
		return fileBak;
	}

	/**
	 * 备份文件
	 * 
	 * @param file
	 * @param fileBak
	 * @return
	 */
	public File SaveBak(File file, File fileBak) {
		file.compareTo(fileBak);
		return fileBak;
	}

	/**
	 * 合并文件
	 * 
	 * @param filePaths
	 *            文件组路径
	 * @param saveUnitePath
	 *            合并后文件路径
	 * @return
	 */
	public File uniteFile(String[] filePaths, String saveUnitePath) {
		StringBuffer sb = new StringBuffer();
		for (String filePath : filePaths) {
			sb.append(loadFile(filePath));
		}
		return saveFile(sb.toString(), saveUnitePath);
	}

	/**
	 * 复制单个文件
	 * 
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf.txt
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf.txt
	 * @return boolean
	 */
	public void copyFile(String oldPath, String newPath) {
		try {
			int bytesum = 0;
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists()) { // 文件存在时
				InputStream inStream = new FileInputStream(oldPath); // 读入原文件
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1444];
				int length;
				while ((byteread = inStream.read(buffer)) != -1) {
					bytesum += byteread; // 字节数 文件大小
					System.out.println(bytesum);
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
			}
		} catch (Exception e) {
			System.out.println("复制单个文件操作出错");
			e.printStackTrace();

		}

	}

	/**
	 * 复制整个文件夹内容
	 * 
	 * @param oldPath
	 *            String 原文件路径 如：c:/fqf
	 * @param newPath
	 *            String 复制后路径 如：f:/fqf/ff
	 * @return boolean
	 */
	public void copyFolder(String oldPath, String newPath) {

		try {
			(new File(newPath)).mkdirs(); // 如果文件夹不存在 则建立新文件夹
			File a = new File(oldPath);
			String[] file = a.list();
			File temp = null;
			for (int i = 0; i < file.length; i++) {
				if (oldPath.endsWith(File.separator)) {
					temp = new File(oldPath + file[i]);
				} else {
					temp = new File(oldPath + File.separator + file[i]);
				}

				if (temp.isFile()) {
					FileInputStream input = new FileInputStream(temp);
					FileOutputStream output = new FileOutputStream(newPath
							+ "/" + (temp.getName()).toString());
					byte[] b = new byte[1024 * 5];
					int len;
					while ((len = input.read(b)) != -1) {
						output.write(b, 0, len);
					}
					output.flush();
					output.close();
					input.close();
				}
				/*
				 * if (temp.isDirectory()) {// 如果是子文件夹 copyFolder(oldPath + "/"
				 * + file[i], newPath + "/" + file[i]); }
				 */
			}
		} catch (Exception e) {
			System.out.println("复制整个文件夹内容操作出错");
			e.printStackTrace();

		}

	}

	/**
	 * 删除文件夹
	 * 
	 * @param filePathAndName
	 *            String 文件夹路径及名称 如c:/fqf
	 * @param fileContent
	 *            String
	 * @return boolean
	 */
	public void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); // 删除空文件夹

		} catch (Exception e) {
			System.out.println("删除文件夹操作出错");
			e.printStackTrace();

		}

	}

	/**
	 * 删除文件夹里面的所有文件
	 * 
	 * @param path
	 *            String 文件夹路径 如 c:/fqf
	 */
	public void delAllFile(String path) {
		File file = new File(path);
		if (!file.exists()) {
			return;
		}
		if (!file.isDirectory()) {
			return;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
			}
		}
	}

	/**
	 * 移动文件到指定目录
	 * 
	 * @param oldPath
	 *            String 如：c:/fqf.txt
	 * @param newPath
	 *            String 如：d:/fqf.txt
	 */
	public void moveFile(String oldPath, String newPath) {
		copyFile(oldPath, newPath);
		delFile(oldPath);

	}

	/**
	 * 移动文件到指定目录
	 * 
	 * @param oldPath
	 *            String 如：c:/fqf.txt
	 * @param newPath
	 *            String 如：d:/fqf.txt
	 */
	public void moveFolder(String oldPath, String newPath) {
		copyFolder(oldPath, newPath);
		delFolder(oldPath);

	}

	/**
	 * 删除文件
	 * 
	 * @param filePathAndName
	 *            String 文件路径及名称 如c:/fqf.txt
	 * @param fileContent
	 *            String
	 * @return boolean
	 */
	public void delFile(String filePathAndName) {
		try {
			String filePath = filePathAndName;
			filePath = filePath.toString();
			java.io.File myDelFile = new java.io.File(filePath);
			myDelFile.delete();

		} catch (Exception e) {
			System.out.println("删除文件操作出错");
			e.printStackTrace();

		}

	}

	/**
	 * 合并文件
	 * 
	 * @param filePath
	 *            路径
	 * @param endsWith
	 *            包含后缀
	 * @param unitePath
	 *            保存合并后文件
	 * @return
	 */
	public File uniteFile(String filePath, String endsWith, String unitePath,
			Boolean isDel) {

		File[] files = new File(filePath).listFiles();
		List<String> list = new ArrayList<String>();
		for (File file : files) {
			if (file.getName().endsWith(endsWith)) {
				list.add(file.getName());
			}
		}
		if (list.isEmpty()) {
			return null;
		}
		return uniteFile(filePath, (String[]) list.toArray(new String[list
				.size()]), unitePath, isDel);
	}

	/**
	 * 
	 * 
	 * 合并文件
	 * 
	 * @param filePaths
	 *            文件组路径
	 * @param fileNames
	 *            文件名称
	 * @param saveUnitePath
	 *            合并后文件路径
	 * @return
	 */
	public File uniteFile(String filePath, String[] fileNames,
			String unitePath, Boolean isDel) {
		StringBuffer sb = new StringBuffer();
		for (String fileName : fileNames) {
			sb.append(loadFile(filePath + "\\" + fileName));
			if (isDel) {
				new File(filePath + "\\" + fileName).delete();
				System.out.println(filePath + "\\" + fileName + "\t\t删除!");
			}
		}
		return saveFile(sb.toString(), unitePath);
	}

	/**
	 * 合并文件名称
	 * 
	 * @param parentPath
	 * @param name
	 * @return
	 */
	public String uniteFilePath(String parentPath, String name) {
		if (parentPath.endsWith("\\")) {
			parentPath += name;
		} else {
			parentPath += "\\" + name;
		}
		return parentPath;
	}

	/**
	 * 合并文件名称
	 * 
	 * @param path
	 * @param name
	 * @return
	 */
	public String uniteFilePath(File path, String name) {
		return path.getPath() + "\\" + name;
	}

	/**
	 * 批量替换文件名称
	 * 
	 * @param path
	 *            文件夹路径
	 * @param inStr
	 *            目标字符
	 * @param replaceStr
	 *            替换字符
	 * @return
	 */
	public File[] replaceFileName(String path, String inStr, String replaceStr) {
		File[] files = new File(path).listFiles();
		List<File> list = new ArrayList<File>();
		for (File file : files) {
			if (file.getName().indexOf(inStr) > 0) {
				File newFile = new File(uniteFilePath(file.getParent(), file
						.getName().replace(inStr, replaceStr)));
				if (file.renameTo(newFile)) {
					System.out.println(file.getName() + "\t\t更改为:\t"
							+ newFile.getName());
					list.add(newFile);
				}
			}
		}
		return list.toArray(new File[list.size()]);
	}

	/**
	 * 批量替换文件名称
	 * 
	 * @param path
	 *            文件夹路径
	 * @param en
	 *            更换方式
	 * @return
	 */
	public File[] replaceFileName(String path, ENaming en) {
		File[] files = new File(path).listFiles();
		List<File> list = new ArrayList<File>();
		for (File file : files) {
			String fileName = file.getName();
			switch (en) {
			case Camel:
				fileName = StringUtil.toCamel(fileName);
				break;
			case DBSimonyi:
				fileName = StringUtil.toDBSimonyi(fileName);
				break;
			case Pascal:
				fileName = StringUtil.toPascal(fileName);
				break;
			}
			File newFile = new File(uniteFilePath(file.getParent(), fileName));
			if (file.renameTo(newFile)) {
				System.out.println(file.getName() + "\t\t更改为:\t"
						+ newFile.getName());
				list.add(newFile);
			}
		}
		return list.toArray(new File[list.size()]);
	}

	/**
	 * 批量替换文件名称
	 * 
	 * @param path
	 *            文件夹路径
	 * @param en
	 *            更换方式
	 * @return
	 */
	public File[] replaceFileName(String path, String inStr, ENaming en) {
		File[] files = new File(path).listFiles();
		List<File> list = new ArrayList<File>();
		for (File file : files) {
			if (file.getName().indexOf(inStr) > 0) {
				String fileName = file.getName();
				switch (en) {
				case Camel:
					fileName = StringUtil.toCamel(fileName);
					break;
				case DBSimonyi:
					fileName = StringUtil.toDBSimonyi(fileName);
					break;
				case Pascal:
					fileName = StringUtil.toPascal(fileName);
					break;
				case simonyiToCamel:
					fileName = StringUtil.simonyiToCamel(fileName);
					break;
				case simonyiToPascal:
					fileName = StringUtil.simonyiToPascal(fileName);
					break;
				}
				File newFile = new File(uniteFilePath(file.getParent(),
						fileName));
				if (file.renameTo(newFile)) {
					file.delete();
					System.out.println(file.getName() + "\t\t更改为:\t"
							+ newFile.getName());
					list.add(newFile);
				}
			}
		}
		return list.toArray(new File[list.size()]);
	}

	/**
	 * 文件搜索
	 * 
	 * @param filePath
	 *            文件路径
	 */
	public void searchFile(String filePath) {
		searchFile(new File(filePath));
	}

	/**
	 * 搜索文件
	 * 
	 * @param file
	 *            文件
	 */
	public void searchFile(File file) {
		if (file.isDirectory() && !file.getName().equals("SwapBak")
				&& !file.getName().equals(".svn")) {
			for (File f : file.listFiles()) {
				searchFile(f);
			}
		} else {
			String name = file.getName();
			// 过虑名称
			for (String neglect : neglectNames) {
				if (name.lastIndexOf(neglect) > 0) {
					return;
				}
			}
			// 过虑后缀
			for (String ext : exts) {
				if (!name.endsWith("." + ext)) {
					return;
				}
			}
			// 包含名称
			for (String fileName : containNames) {
				if (name.indexOf(fileName) < 0) {
					return;
				}
			}
			files.add(file);
			filePaths.add(file.getPath());
			filePrefixs.add(StringUtil.getFilePrefix(file));
			fileNames.add(StringUtil.getFileNameNotPrefix(file));
			fileNameAndExts.add(file.getName());
		}
	}

	/**
	 * 判断字符串的编码
	 * 
	 * @param str
	 * @return
	 */
	private String getEncoding(String str) {
		String encode = "GB2312";
		try {
			if (str.equals(new String(str.getBytes(encode), encode))) {
				String s = encode;
				return s;
			}
		} catch (Exception exception) {
		}
		encode = "ISO-8859-1";
		try {
			if (str.equals(new String(str.getBytes(encode), encode))) {
				String s1 = encode;
				return s1;
			}
		} catch (Exception exception1) {
		}
		encode = "UTF-8";
		try {
			if (str.equals(new String(str.getBytes(encode), encode))) {
				String s2 = encode;
				return s2;
			}
		} catch (Exception exception2) {
		}
		encode = "GBK";
		try {
			if (str.equals(new String(str.getBytes(encode), encode))) {
				String s3 = encode;
				return s3;
			}
		} catch (Exception exception3) {
		}
		encode = "BIG5";
		try {
			if (str.equals(new String(str.getBytes(encode), encode))) {
				String s4 = encode;
				return s4;
			}
		} catch (Exception exception3) {
		}
		return "";
	}

	/**
	 * 过滤路径
	 * 
	 * @param path
	 * @return
	 */
	private synchronized static String repPath(String path) {
		return path.replace("file:/", "").replace("src", "").replace("bin", "")
				.replace("/WebRoot", "").replace("/WEB-INF/classes", "");
	}

	/* --------------------- GET / SET --------------------- */

	public List<File> getFiles() {
		return files;
	}

	public List<String> getFilePaths() {
		return filePaths;
	}

	public List<String> getFileNameAndExts() {
		return fileNameAndExts;
	}

	public List<String> getFileNames() {
		return fileNames;
	}

	public List<String> getFilePrefixs() {
		return filePrefixs;
	}
}
